﻿using Common.Communication;
using DeviceBase.Enums;
using DeviceBase.Interfaces;
using DeviceBase.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace JueYuanNaiYa.Core.Eec
{
    public class EEC7473NiVisa : NiVisaBase, IJueYuanNaiYa
    {
        public string Name { get; set; }
        public EEC7473NiVisa(string name, string sn, int timeout = 1500) : base(sn, timeout)
        {
            Name = name;
        }
        public Result<bool> NewTest(int steps)
        {
            return new Result<bool>(true);
        }

        public Result<bool> SetBeep(bool isOn)
        {
            return new Result<bool>(true);
        }

        public Result<bool> SetTest(JueYuanNaiYaEnum.JueYuanNaiYaMode mode, int step,
            double vol, double upTime, double downTime, double keepTime,
            double min, double max,
            int freq = 0, double arc = 0)
        {
            Result<bool> result = new Result<bool>();
            AppendInfo(Name, $"设置测试参数");
            AppendInfo(Name, $"切换到测试程序1");
            var command = CmdAcw;
            var re = WriteThenRead(command);
            if (!re.IsSucceed)
            {
                result.IsSucceed = false;
                result.Err = "切换到测试程序1失败";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            string type = "";
            switch (mode)
            {
                case JueYuanNaiYaEnum.JueYuanNaiYaMode.交流耐压:
                    type = "AC";
                    break;
                default:
                    result.IsSucceed = false;
                    result.Err = mode.ToString() + "暂不支持";
                    AppendResult(Name, result.Err);
                    return result.EndTime();
            }
            if (type == "AC")
            {
                AppendInfo(Name, $"设置频率{freq}Hz");
                command = CmdFreq(freq == 50 ? 0 : 1);
                re = WriteThenRead(command);
                if (!re.IsSucceed)
                {
                    result.IsSucceed = false;
                    result.Err = "设置频率失败";
                    AppendResult(Name, result.Err);
                    return result.EndTime();
                }
                Thread.Sleep(100);
                command = CmdGetFreq;
                re = WriteThenRead(command);
                if (!re.IsSucceed || !int.TryParse(re.Value, out int va) || va != freq)
                {
                    result.IsSucceed = false;
                    result.Err = "设置频率失败";
                    AppendResult(Name, result.Err);
                    return result.EndTime();
                }
                AppendInfo(Name, $"设置电弧OFF");
                command = CmdArcOff;
                re = WriteThenRead(command);
                if (!re.IsSucceed)
                {
                    result.IsSucceed = false;
                    result.Err = "设置电弧OFF失败";
                    AppendResult(Name, result.Err);
                    return result.EndTime();
                }
                Thread.Sleep(100);
                command = CmdGetArc;
                re = WriteThenRead(command);
                if (!re.IsSucceed || !int.TryParse(re.Value, out int val) || val != 0)
                {
                    result.IsSucceed = false;
                    result.Err = "设置电弧OFF失败";
                    AppendResult(Name, result.Err);
                    return result.EndTime();
                }
            }
            AppendInfo(Name, $"设置电压{vol}V");
            command = CmdSetVol(vol);
            re = WriteThenRead(command);
            if (!re.IsSucceed)
            {
                result.IsSucceed = false;
                result.Err = "设置电压失败";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            Thread.Sleep(100);
            command = CmdGetVol;
            re = WriteThenRead(command);
            if (!re.IsSucceed || !double.TryParse(re.Value, out double v) || v != vol)
            {
                result.IsSucceed = false;
                result.Err = "设置电压失败";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            AppendInfo(Name, $"设置时间单位s");
            command = CmdTimeUnit;
            re = WriteThenRead(command);
            if (!re.IsSucceed)
            {
                result.IsSucceed = false;
                result.Err = "设置时间单位s失败";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            Thread.Sleep(100);
            command = CmdGetTimeUnit;
            re = WriteThenRead(command);
            if (!re.IsSucceed || !re.Value.Contains("0"))
            {
                result.IsSucceed = false;
                result.Err = "设置时间单位s失败";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            AppendInfo(Name, $"设置上升时间{upTime}s");
            command = CmdUpTime(upTime);
            re = WriteThenRead(command);
            if (!re.IsSucceed)
            {
                result.IsSucceed = false;
                result.Err = "设置上升时间失败";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            Thread.Sleep(100);
            command = CmdGetUpTime;
            re = WriteThenRead(command);
            if (!re.IsSucceed || !double.TryParse(re.Value, out double ut) || ut != upTime)
            {
                result.IsSucceed = false;
                result.Err = "设置上升时间失败";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            AppendInfo(Name, $"设置保持时间{keepTime}s");
            command = CmdKeepTime(keepTime);
            re = WriteThenRead(command);
            if (!re.IsSucceed)
            {
                result.IsSucceed = false;
                result.Err = "设置保持时间失败";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            Thread.Sleep(100);
            command = CmdGetKeepTime;
            re = WriteThenRead(command);
            if (!re.IsSucceed || !double.TryParse(re.Value, out double kt) || kt != keepTime)
            {
                result.IsSucceed = false;
                result.Err = "设置保持时间失败";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            AppendInfo(Name, $"设置下降时间{downTime}s");
            command = CmdDownTime(downTime);
            re = WriteThenRead(command);
            if (!re.IsSucceed)
            {
                result.IsSucceed = false;
                result.Err = "设置下降时间失败";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            Thread.Sleep(100);
            command = CmdGetDownTime;
            re = WriteThenRead(command);
            if (!re.IsSucceed || !double.TryParse(re.Value, out double dt) || dt != downTime)
            {
                result.IsSucceed = false;
                result.Err = "设置下降时间失败";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            AppendInfo(Name, $"设置上限{max}");
            command = CmdMax(max);
            re = WriteThenRead(command);
            if (!re.IsSucceed)
            {
                result.IsSucceed = false;
                result.Err = "设置上限失败";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            Thread.Sleep(100);
            command = CmdGetMax;
            re = WriteThenRead(command);
            if (!re.IsSucceed || !double.TryParse(re.Value, out double ma) || ma != max)
            {
                result.IsSucceed = false;
                result.Err = "设置上限失败";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            AppendInfo(Name, $"设置下限{min}");
            command = CmdMin(min);
            re = WriteThenRead(command);
            if (!re.IsSucceed)
            {
                result.IsSucceed = false;
                result.Err = "设置下限失败";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            Thread.Sleep(100);
            command = CmdGetMin;
            re = WriteThenRead(command);
            if (!re.IsSucceed || !double.TryParse(re.Value, out double mi) || mi != min)
            {
                result.IsSucceed = false;
                result.Err = "设置下限失败";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            AppendInfo(Name, $"设置测试参数成功");
            return result.EndTime();
        }

        public Result<List<JueYuanNaiYaResult>> StartTest(int timeout)
        {
            Result<List<JueYuanNaiYaResult>> result = new Result<List<JueYuanNaiYaResult>>();
            AppendInfo(Name, $"开始测试");
            var command = CmdStart;
            var re = WriteThenRead(command);
            if (!re.IsSucceed)
            {
                result.IsSucceed = false;
                result.Err = "开始测试失败";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            DateTime testTime = DateTime.Now.AddSeconds(timeout);
            while (DateTime.Now < testTime)
            {
                Thread.Sleep(500);
                if (DeviceBase.DeviceServer.IsStop)
                {
                    Write(CmdStop);
                    result.IsSucceed = false;
                    result.Err = "停止测试";
                    AppendResult(Name, result.Err);
                    return result.EndTime();
                }
                //todo 失败停止
            }
            command = CmdFetch;
            re = WriteThenRead(command);
            if (!re.IsSucceed || re.Value.Count(o => o == ',') != 6)
            {
                Write(CmdStop);
                result.IsSucceed = false;
                result.Err = "测试失败";
                AppendResult(Name, result.Err);
                return result.EndTime();
            }
            //M1,ACW,Pass,0.01,0.000,5.0,1
            var value = re.Value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
            JueYuanNaiYaResult jueYuanNai = new JueYuanNaiYaResult()
            {
                type = value[1],
                value = value[3] + "kV," + value[4] + "mA",
                isPass = value[2].Contains("Pass"),
            };
            AppendResult(Name, jueYuanNai.type + "," + jueYuanNai.value + "," + jueYuanNai.isPass);
            result.Value.Add(jueYuanNai);
            result.IsSucceed = result.Value.Count(o => o.isPass == false) == 0;
            if (!result.IsSucceed)
                re.Err = "测试未通过";
            return result.EndTime();
        }

        public Result<bool> StopTest()
        {
            Result<bool> result = new Result<bool>();
            AppendInfo(Name, $"停止测试");
            List<string> temps = new List<string>();
            var command = CmdStop;
            var re = Write(command);
            if (!re.IsSucceed)
            {
                result.IsSucceed = false;
                result.Err = "停止测试失败";
                AppendResult(Name, result.Err);
            }
            AppendInfo(Name, $"停止测试成功");
            return result.EndTime();
        }
        string CmdAcw => $"FL 1\n";
        string CmdFreq(int freq) { return "EF " + freq + "\n"; }
        string CmdGetFreq => "EF?\n";
        string CmdArcOff => "EAD 0\n";
        string CmdGetArc => "EAD? \n";
        string CmdSetVol(double vol) { return "EV " + vol/1000 + "\n"; }
        string CmdGetVol => "EV?\n";
        string CmdTimeUnit => "ERWU 0\n";
        string CmdGetTimeUnit => "ERWU?\n";
        string CmdUpTime(double time) { return "ERU " + time + "\n"; }
        string CmdGetUpTime => "ERU?\n";
        string CmdKeepTime(double time) { return "EDW " + time + "\n"; }
        string CmdGetKeepTime => "EDW?\n";
        string CmdDownTime(double time) { return "ERD " + time + "\n"; }
        string CmdGetDownTime => "ERD?\n";
        string CmdMin(double min) { return "EL " + (min * 1000) + "\n"; }
        string CmdGetMin => "EL?\n";
        string CmdMax(double max) { return "EH " + (max * 1000) + "\n"; }
        string CmdGetMax => "EH?\n";
        string CmdStart => "TEST\n";
        string CmdStop => "RESET\n";
        string CmdFetch => "TD?\n";
    }
}
